#include "lxz_config.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#ifdef LXZ_CFG_OS_WIN32
  #define _WIN32_WINNT 0x400
  #include <direct.h>
  #include <io.h>
  #include <windows.h>
  #include <errno.h>
#endif /* LXZ_CFG_OS_WIN32 */

#ifdef LXZ_CFG_OS_LINUX
  #include <sys/types.h>
  #include <sys/socket.h>
  #include <arpa/inet.h>
#endif /* LXZ_CFG_OS_LINUX */

#include "lxz_types.h"
#include "lxz_string.h"
#include "lxz_runlog.h"
#include "lxz_debug.h"
#include "lxz_exec.h"
#include "os_port.h"

#include "udtserver.h"

/*
 * The structure of version string
 * -- Major.Minor.RefixID
 */
#define UDT_SVR_VERSION_FULL "UDTServer-2.0.0"
#define UDT_SVR_COMPILE_DATE (__DATE__)
#define UDT_SVR_COMPILE_TIME (__TIME__)

#define UDT_UL_REL_DIRECTORY "upload"
#define UDT_DL_REL_DIRECTORY "download"

static uint32 ThreadTCPService(void* lpParam);
static uint32 ThreadUDPService(void* lpParam);

static uint32 udt_f_tcpserver_SendFile(void* pctxt);
static uint32 udt_f_tcpserver_RecvFile(void* pctxt);
static uint32 udt_f_tcpserver_ListFile(void* pctxt);
static uint32 udt_f_tcpserver_SendRecved(void* pctxt);
static sint32 udt_f_tcpserver_start(uint16 u_svr_port);
static sint32 udt_f_udpserver_start(uint16 u_svr_port);

static sint32 udt_f_incmd_cmdtype(const uint08* p_udt_cmd, sint32 i_cmd_len);
static sint32 udt_f_incmd_cmdparam(uint08* p_udt_cmd, uint08* p_udt_param1, sint32* p_udt_param2);

static sint32 udt_f_logfile_new(void* arg);

typedef struct _udt_incmd_t
{
    sint08* incmd_str;
    sint32 incmd_type;
}udt_incmd_t;

typedef enum
{
    UIT_CMD_TYPE_DOWNLOAD,
    UIT_CMD_TYPE_UPLOAD,
    UIT_CMD_TYPE_LISTFILE,
    UIT_CMD_TYPE_INVALID
}UDT_INCMD_TYPE_E;

static udt_incmd_t gs_udt_incmd_table[] =
{
    {"DT:", UIT_CMD_TYPE_DOWNLOAD},
    {"UT:", UIT_CMD_TYPE_UPLOAD},
#ifdef LXZ_CFG_OS_WIN32
    {"LT:", UIT_CMD_TYPE_LISTFILE},
#endif /* LXZ_CFG_OS_WIN32 */
    {0, UIT_CMD_TYPE_INVALID}
};

static sint32 udt_f_tcpserver_start(uint16 u_svr_port)
{
    sint32 i_ret_val = 0;

    sint32 i_op_status = 0;
    sint32 i_svr_socket = 0;
    sint32 i_new_socket = 0;
    udt_context_t * p_udt_ctxt = NULL;

    if((i_svr_socket = osp_socket_f_open(AF_INET,SOCK_STREAM,0)) == 0)
    {
        OS_DBG_URC(("tcpserver: osp_socket_f_open fail;\r\n"));
        return -1;
    }

    if(osp_socket_f_bind(i_svr_socket, u_svr_port) == 0)
    {
        OS_DBG_URC(("tcpserver: osp_socket_f_bind fail;\r\n"));
        osp_socket_f_close(i_svr_socket);
        return -1;
    }

    if(osp_socket_f_listen(i_svr_socket, UDT_MAX_BACK_LOG) == 0)
    {
        OS_DBG_URC(("tcpserver: osp_socket_f_listen fail;\r\n"));
        osp_socket_f_close(i_svr_socket);
        return -1;
    }

    while (1)
    {
        p_udt_ctxt = (udt_context_t *)malloc(sizeof(udt_context_t));
        if(p_udt_ctxt == NULL)
        {
            i_ret_val = -1;
            break;
        }
        
        memset(p_udt_ctxt, 0, sizeof(udt_context_t));
        p_udt_ctxt->p_rw_buff = (sint08 *)malloc(UDT_DEF_BUFF_SIZE);
        if(p_udt_ctxt->p_rw_buff == NULL)
        {
            osp_socket_f_close(i_svr_socket);
            free(p_udt_ctxt);

            i_ret_val = -1;
            break;
        }

        if ((i_new_socket = osp_socket_f_accept(i_svr_socket))==0)
        {
            osp_socket_f_close(i_svr_socket);
            free(p_udt_ctxt->p_rw_buff);
            free(p_udt_ctxt);

            i_ret_val = -1;
            break;
        }
        
        p_udt_ctxt->lsockfd = i_svr_socket;
        p_udt_ctxt->csockfd = i_new_socket;
        
        i_op_status = osp_thread_f_open(ThreadTCPService, p_udt_ctxt,
            &(p_udt_ctxt->iThreadID));
        
        if (i_op_status == 0)
        {
            osp_socket_f_close(p_udt_ctxt->csockfd);
            free(p_udt_ctxt->p_rw_buff);
            free(p_udt_ctxt);
        }
    }

    return i_ret_val;
}

static sint32 udt_f_udpserver_start(uint16 u_svr_port)
{
    sint32 i_ret_val = 0;

    sint32 i_op_status = 0;
    sint32 i_svr_socket = 0;
    udt_context_t * p_udt_ctxt = NULL;

    p_udt_ctxt = (udt_context_t *)malloc(sizeof(udt_context_t));
    if(p_udt_ctxt == NULL)
    {
        return -1;
    }

    memset(p_udt_ctxt, 0, sizeof(udt_context_t));
    p_udt_ctxt->p_rw_buff = (sint08 *)malloc(UDT_MAX_BUFF_SIZE);
    if(p_udt_ctxt->p_rw_buff == NULL)
    {
        free(p_udt_ctxt);
        return -1;
    }

    if((i_svr_socket = osp_socket_f_open(AF_INET,SOCK_DGRAM,0)) == 0)
    {
        OS_DBG_URC(("udpserver: osp_socket_f_open fail;\r\n"));
        free(p_udt_ctxt->p_rw_buff);
        free(p_udt_ctxt);
        return -1;
    }

    if(osp_socket_f_bind(i_svr_socket, u_svr_port) == 0)
    {
        OS_DBG_URC(("udpserver: osp_socket_f_bind fail;\r\n"));
        osp_socket_f_close(i_svr_socket);
        free(p_udt_ctxt->p_rw_buff);
        free(p_udt_ctxt);
        return -1;
    }

    p_udt_ctxt->lsockfd = i_svr_socket;
    p_udt_ctxt->csockfd = i_svr_socket;

    i_op_status = osp_thread_f_open(ThreadUDPService, p_udt_ctxt,
        &(p_udt_ctxt->iThreadID));
    
    if (i_op_status == 0)
    {
        osp_socket_f_close(p_udt_ctxt->csockfd);
        free(p_udt_ctxt->p_rw_buff);
        free(p_udt_ctxt);
        p_udt_ctxt = NULL;
    }

    return i_ret_val;
}

static sint32 udt_f_incmd_cmdtype(const uint08* p_udt_cmd, sint32 i_cmd_len)
{
    sint32 i = 0;
    sint32 i_head_len = 0;
    sint32 i_cmd_type = UIT_CMD_TYPE_INVALID;

    udt_incmd_t* p_tmp_incmd = NULL;

    if (p_udt_cmd == NULL)
    {
        return i_cmd_type;
    }

    if (i_cmd_len > UDT_CMD_MAX_LEN)
    {
        return i_cmd_type;
    }

    if (NULL != strchr(p_udt_cmd, '/') || NULL != strchr(p_udt_cmd, '\\'))
    {
        return i_cmd_type;
    }

    p_tmp_incmd = &(gs_udt_incmd_table[0]);
    while (p_tmp_incmd->incmd_str != NULL)
    {
        i_head_len = strlen(p_tmp_incmd->incmd_str);
        if (0 == strncmp(p_tmp_incmd->incmd_str, p_udt_cmd, i_head_len))
        {
            i_cmd_type = p_tmp_incmd->incmd_type;
            break;
        }
        
        p_tmp_incmd++;
    }

    return i_cmd_type;
}

static sint32 udt_f_incmd_cmdparam(uint08* p_udt_cmd, uint08* p_udt_param1, sint32* p_udt_param2)
{
    sint32 i_op_status = 0;

    sint32 i_nb_param = 0;
    uint08 p_udt_head[8];
    uint08 i_tail_char1;
    uint08 i_tail_char2;
    if ((p_udt_cmd == NULL)||(p_udt_param1 == NULL)||(p_udt_param2 == NULL))
    {
        return i_op_status;
    }

    memset(p_udt_head, 0, sizeof(p_udt_head));
    i_nb_param = sscanf(p_udt_cmd, "%[^:]:%[^:]:%d%c%c", p_udt_head, 
        p_udt_param1, p_udt_param2, &i_tail_char1, &i_tail_char2);
    if (i_nb_param == 3)
    {
        i_op_status = 1;
    }
    else if ((i_nb_param == 4) && (i_tail_char1==0x0d || i_tail_char1==0x0a))
    {
        i_op_status = 1;
    }
    else
    {
        i_op_status = 0;
    }

    return i_op_status;
}

static uint32 udt_f_tcpserver_SendFile(void* pctxt)
{
    udt_context_t * p_udt_ctxt = (udt_context_t *)pctxt;

    FILE* fp_send = NULL;

    sint32 i_read_len = 0;
    sint32 i_pos_start = 0;
    sint32 i_total_len = 0;

    sint08 p_real_directory[LXZ_PATH_LENGTH_MAX];

    OS_DBG_LOG(("iID:%u, Download service, start!\r\n", p_udt_ctxt->iThreadID));
    OS_DBG_LOG(("iID:%u, Download service, fn:%s, os=%d\r\n", 
        p_udt_ctxt->iThreadID, p_udt_ctxt->op_param1, p_udt_ctxt->op_param2));

    OS_DBG_URC(("iID:%u, Download service, start!\r\n", p_udt_ctxt->iThreadID));
    OS_DBG_URC(("iID:%u, Download service, fn:%s, os=%d;\r\n", 
        p_udt_ctxt->iThreadID, p_udt_ctxt->op_param1, p_udt_ctxt->op_param2));

    memset(p_udt_ctxt->p_rw_buff, 0, UDT_DEF_BUFF_SIZE);
    memset(p_real_directory, 0, sizeof(p_real_directory));
    sprintf(p_real_directory, "%s/%s", lxz_root_directory_f_get(), UDT_DL_REL_DIRECTORY);

    fp_send = osp_file_f_fopen(p_real_directory, p_udt_ctxt->op_param1, "rb");
    if (fp_send != NULL)
    {
        OS_DBG_LOG(("iID:%u, Download service, fn:%s opened;\r\n",
            p_udt_ctxt->iThreadID, p_udt_ctxt->op_param1));

        OS_DBG_URC(("iID:%u, Download service, fn:%s opened;\r\n",
            p_udt_ctxt->iThreadID, p_udt_ctxt->op_param1));

        i_pos_start = p_udt_ctxt->op_param2;
        i_total_len = p_udt_ctxt->op_param2;
        OS_DBG_LOG(("iID:%u, Download service, fn:%s, send=%d;\r\n",
            p_udt_ctxt->iThreadID, p_udt_ctxt->op_param1, i_total_len));

        fseek(fp_send, i_pos_start, SEEK_SET);
        memset(p_udt_ctxt->p_rw_buff, 0, UDT_DEF_BUFF_SIZE);
        i_read_len = fread(p_udt_ctxt->p_rw_buff, 1, UDT_DEF_BUFF_SIZE, fp_send);
        while (i_read_len > 0)
        {
            i_total_len = i_total_len + i_read_len;
            osp_socket_f_write(p_udt_ctxt->csockfd, p_udt_ctxt->p_rw_buff, i_read_len);
            
            memset(p_udt_ctxt->p_rw_buff, 0, UDT_DEF_BUFF_SIZE);
            i_read_len = fread(p_udt_ctxt->p_rw_buff, 1, UDT_DEF_BUFF_SIZE, fp_send);
            
            OS_DBG_LOG(("iID:%u, Download service, fn:%s, send=%d;\r\n",
                p_udt_ctxt->iThreadID, p_udt_ctxt->op_param1, i_total_len));
            osp_timer_f_sleep(10);
        }
        
        fclose(fp_send);
        osp_socket_f_close(p_udt_ctxt->csockfd);

        OS_DBG_LOG(("iID:%u, Download service, fn:%s, closed;\r\n", 
            p_udt_ctxt->iThreadID, p_udt_ctxt->op_param1));
        OS_DBG_URC(("iID:%u, Download service, fn:%s, closed;\r\n", 
            p_udt_ctxt->iThreadID, p_udt_ctxt->op_param1));
    }
    else
    {
        char * p_not_found = "file not found!";
        
        OS_DBG_LOG(("iID:%u, Download service, fn:%s not found;\r\n", 
            p_udt_ctxt->iThreadID, p_udt_ctxt->op_param1));
        OS_DBG_URC(("iID:%u, Download service, fn:%s not found;\r\n", 
            p_udt_ctxt->iThreadID, p_udt_ctxt->op_param1));
        
        osp_socket_f_write(p_udt_ctxt->csockfd, p_not_found, strlen(p_not_found));
        osp_socket_f_close(p_udt_ctxt->csockfd);
    }

    OS_DBG_LOG(("iID:%u, Download service, stop.\r\n", p_udt_ctxt->iThreadID));
    OS_DBG_URC(("iID:%u, Download service, stop.\r\n", p_udt_ctxt->iThreadID));

    free(p_udt_ctxt->p_rw_buff);
    free(p_udt_ctxt);

    return 0;
}

static uint32 udt_f_tcpserver_RecvFile(void* pctxt)
{
    udt_context_t * p_udt_ctxt = (udt_context_t *)pctxt;

    FILE* fp_recv = NULL;
    sint32 i_read_len = 0;
    sint32 i_pos_start = 0;
    sint32 i_total_len = 0;

    sint32 i_dir_exist = 0;
    sint08 p_real_directory[LXZ_PATH_LENGTH_MAX];

    OS_DBG_LOG(("iID:%u, Upload service, start.\r\n", p_udt_ctxt->iThreadID));
    OS_DBG_LOG(("iID:%u, Upload service, fn:%s, os=%d;\r\n", p_udt_ctxt->iThreadID,
        p_udt_ctxt->op_param1, p_udt_ctxt->op_param2));

    OS_DBG_URC(("iID:%u, Upload service, start.\r\n", p_udt_ctxt->iThreadID));
    OS_DBG_URC(("iID:%u, Upload service, fn:%s, os=%d;\r\n", p_udt_ctxt->iThreadID,
        p_udt_ctxt->op_param1, p_udt_ctxt->op_param2));

    memset(p_udt_ctxt->p_rw_buff, 0, UDT_DEF_BUFF_SIZE);
    memset(p_real_directory, 0, sizeof(p_real_directory));
    sprintf(p_real_directory, "%s/%s", lxz_root_directory_f_get(), UDT_UL_REL_DIRECTORY);

    fp_recv = osp_file_f_fopen(p_real_directory, p_udt_ctxt->op_param1, "wb+");
    if (fp_recv != NULL)
    {
        OS_DBG_LOG(("iID:%u, Upload service, fn:%s opened;\r\n", 
            p_udt_ctxt->iThreadID, p_udt_ctxt->op_param1));

        OS_DBG_URC(("iID:%u, Upload service, fn:%s opened;\r\n", 
            p_udt_ctxt->iThreadID, p_udt_ctxt->op_param1));

        i_pos_start = p_udt_ctxt->op_param2;
        i_total_len = p_udt_ctxt->op_param2;
        OS_DBG_LOG(("iID:%u, Upload service, fn:%s, recv=%d;\r\n", 
            p_udt_ctxt->iThreadID, p_udt_ctxt->op_param1, i_total_len));

        fseek(fp_recv, i_pos_start, SEEK_SET);
        memset(p_udt_ctxt->p_rw_buff, 0, UDT_DEF_BUFF_SIZE);
        i_read_len = osp_socket_f_read(p_udt_ctxt->csockfd, p_udt_ctxt->p_rw_buff, UDT_DEF_BUFF_SIZE);
        while (i_read_len > 0)
        {
            i_total_len = i_total_len + i_read_len;
            fwrite(p_udt_ctxt->p_rw_buff, 1, i_read_len, fp_recv);
            fflush(fp_recv);
            
            memset(p_udt_ctxt->p_rw_buff, 0, UDT_DEF_BUFF_SIZE);
            i_read_len = osp_socket_f_read(p_udt_ctxt->csockfd, p_udt_ctxt->p_rw_buff, UDT_DEF_BUFF_SIZE);
            
            OS_DBG_LOG(("iID:%u, Upload service, fn:%s, recv=%d;\r\n",
                p_udt_ctxt->iThreadID, p_udt_ctxt->op_param1, i_total_len));
            osp_timer_f_sleep(10);
        }
        
        fclose(fp_recv);
        osp_socket_f_close(p_udt_ctxt->csockfd);

        OS_DBG_LOG(("iID:%u, Upload service, fn:%s, closed;\r\n", 
            p_udt_ctxt->iThreadID, p_udt_ctxt->op_param1));
        OS_DBG_URC(("iID:%u, Upload service, fn:%s, closed;\r\n", 
            p_udt_ctxt->iThreadID, p_udt_ctxt->op_param1));
    }
    else
    {
        char * p_error_info = "file been opened or unkwon errors!";
        
        OS_DBG_LOG(("iID:%u, Upload service, fn:%s unopened;\r\n", 
            p_udt_ctxt->iThreadID, p_udt_ctxt->op_param1));

        OS_DBG_URC(("iID:%u, Upload service, fn:%s unopened;\r\n", 
            p_udt_ctxt->iThreadID, p_udt_ctxt->op_param1));
        
        osp_socket_f_write(p_udt_ctxt->csockfd, p_error_info, strlen(p_error_info));
        osp_socket_f_close(p_udt_ctxt->csockfd);
    }

    OS_DBG_LOG(("iID:%u, Upload service, stop.\r\n", p_udt_ctxt->iThreadID));
    OS_DBG_URC(("iID:%u, Upload service, stop.\r\n", p_udt_ctxt->iThreadID));

    free(p_udt_ctxt->p_rw_buff);
    free(p_udt_ctxt);

    return 0;
}

static uint32 udt_f_tcpserver_ListFile(void* pctxt)
{
#ifdef LXZ_CFG_OS_WIN32
    udt_context_t * p_udt_ctxt = (udt_context_t *)pctxt;

    sint32 i_info_len = 0;
    sint32 i_dir_exist = 0;
    sint32 i_fnd_handle = 0;
    struct _finddata_t a_file_info;

    uint08 p_to_search[UDT_MIN_BUFF_SIZE];

    OS_DBG_LOG(("iID:%u, List service, start.\r\n", p_udt_ctxt->iThreadID));
    OS_DBG_LOG(("iID:%u, List service, dir:%s, r=%d;\r\n", p_udt_ctxt->iThreadID,
        p_udt_ctxt->op_param1, p_udt_ctxt->op_param2));

    OS_DBG_URC(("iID:%u, List service, start.\r\n", p_udt_ctxt->iThreadID));
    OS_DBG_URC(("iID:%u, List service, dir:%s, r=%d;\r\n", p_udt_ctxt->iThreadID,
        p_udt_ctxt->op_param1, p_udt_ctxt->op_param2));

    i_dir_exist = _access(p_udt_ctxt->op_param1, 0/*Existence Only*/);
    if (i_dir_exist == 0)
    {
        OS_DBG_LOG(("iID:%u, List service, dir:%s exist;\r\n", 
            p_udt_ctxt->iThreadID, p_udt_ctxt->op_param1));

        OS_DBG_URC(("iID:%u, List service, dir:%s exist;\r\n", 
            p_udt_ctxt->iThreadID, p_udt_ctxt->op_param1));
        
        i_info_len = sprintf(p_to_search, "./%s/*.*", p_udt_ctxt->op_param1);
        i_fnd_handle = _findfirst(p_to_search, &a_file_info);
        if (i_fnd_handle != -1)
        {
            do {
                memset(p_udt_ctxt->p_rw_buff, 0, UDT_DEF_BUFF_SIZE);
                i_info_len = sprintf(p_udt_ctxt->p_rw_buff, "%s\t%d\t%d", a_file_info.name,
                    a_file_info.size, (a_file_info.attrib==0x00000010));
                osp_socket_f_write(p_udt_ctxt->csockfd, p_udt_ctxt->p_rw_buff, i_info_len);
                osp_socket_f_write(p_udt_ctxt->csockfd, "\r\n", 2);
                
                OS_DBG_LOG(("iID:%u, List service, info:%s;\r\n",
                    p_udt_ctxt->iThreadID, p_udt_ctxt->p_rw_buff));
                osp_timer_f_sleep(10);
            }while(0 == _findnext(i_fnd_handle, &a_file_info));
        }

        _findclose(i_fnd_handle);
        osp_socket_f_close(p_udt_ctxt->csockfd);
    }
    else
    {
        char * p_error_info = "directory not exists or unkwon errors!";
        
        OS_DBG_LOG(("iID:%u, List service, dir:%s not exists;\r\n", 
            p_udt_ctxt->iThreadID, p_udt_ctxt->op_param1));

        OS_DBG_URC(("iID:%u, List service, dir:%s not exists;\r\n", 
            p_udt_ctxt->iThreadID, p_udt_ctxt->op_param1));
        
        osp_socket_f_write(p_udt_ctxt->csockfd, p_error_info, strlen(p_error_info));
        osp_socket_f_close(p_udt_ctxt->csockfd);
    }

    OS_DBG_LOG(("iID:%u, List service, stop.\r\n", p_udt_ctxt->iThreadID));
    OS_DBG_URC(("iID:%u, List service, stop.\r\n", p_udt_ctxt->iThreadID));

    free(p_udt_ctxt->p_rw_buff);
    free(p_udt_ctxt);
#endif /* LXZ_CFG_OS_WIN32 */
    return 0;
}

static uint32 udt_f_tcpserver_SendRecved(void* pctxt)
{
    udt_context_t * p_udt_ctxt = (udt_context_t *)pctxt;

    sint32 i_recv_len = 0;
    sint32 i_echo_times = 0;

    OS_DBG_LOG(("iID:%u, TCPEcho service, start.\r\n", p_udt_ctxt->iThreadID));
    OS_DBG_URC(("iID:%u, TCPEcho service, start.\r\n", p_udt_ctxt->iThreadID));
    while (1)
    {
        memset(p_udt_ctxt->p_rw_buff, 0, UDT_DEF_BUFF_SIZE);
        i_recv_len = osp_socket_f_read(p_udt_ctxt->csockfd,
            p_udt_ctxt->p_rw_buff, UDT_DEF_BUFF_SIZE);

        if(i_recv_len > 0)
        {
            i_echo_times++;
            OS_DBG_LOG(("iID:%u, TCPEcho service, times=%d.\r\n",
                p_udt_ctxt->iThreadID, i_echo_times));

            osp_socket_f_write(p_udt_ctxt->csockfd, 
                p_udt_ctxt->p_rw_buff, i_recv_len);
        }
        else
        {
            break;
        }
        
        osp_timer_f_sleep(10);
    }

    OS_DBG_LOG(("iID:%u, TCPEcho service, stop.\r\n", p_udt_ctxt->iThreadID));
    OS_DBG_URC(("iID:%u, TCPEcho service, stop.\r\n", p_udt_ctxt->iThreadID));

    osp_socket_f_close(p_udt_ctxt->csockfd);
    free(p_udt_ctxt->p_rw_buff);
    free(p_udt_ctxt);

    return 0;
}

static uint32 ThreadTCPService(void* lpParam)
{
    sint32 i_recv_len = 0;
    uint32 u_thread_id = 0;
    udt_context_t * p_udt_ctxt = (udt_context_t *)lpParam;
    
    sint32 i_op_status = 0;
    uint08 p_cmd_param1[UDT_MIN_BUFF_SIZE];
    uint32 u_cmd_param2;
    /* create a new thread to recv/send data */
    if (p_udt_ctxt != NULL)
    {
        u_thread_id = p_udt_ctxt->iThreadID;
        OS_DBG_LOG(("iID:%u, TCPService, start!\r\n", u_thread_id));
        OS_DBG_URC(("iID:%u, TCPService, start!\r\n", u_thread_id));

        memset(p_udt_ctxt->p_rw_buff,0,UDT_DEF_BUFF_SIZE);
        i_recv_len = osp_socket_f_read(p_udt_ctxt->csockfd, 
            p_udt_ctxt->p_rw_buff, UDT_DEF_BUFF_SIZE);
        
        p_udt_ctxt->op_type = udt_f_incmd_cmdtype(p_udt_ctxt->p_rw_buff, i_recv_len);
        switch(p_udt_ctxt->op_type)
        {
        case UIT_CMD_TYPE_DOWNLOAD:
            {
                i_op_status = udt_f_incmd_cmdparam(p_udt_ctxt->p_rw_buff, 
                    p_cmd_param1, &u_cmd_param2);
                if (1 == i_op_status)
                {
                    strcpy(p_udt_ctxt->op_param1, p_cmd_param1);
                    p_udt_ctxt->op_param2 = u_cmd_param2;
                    udt_f_tcpserver_SendFile(p_udt_ctxt);
                }
                else
                {
                    osp_socket_f_write(p_udt_ctxt->csockfd, 
                        p_udt_ctxt->p_rw_buff, i_recv_len);
                    udt_f_tcpserver_SendRecved(p_udt_ctxt);
                }
                break;
            }

        case UIT_CMD_TYPE_UPLOAD:
            {
                i_op_status = udt_f_incmd_cmdparam(p_udt_ctxt->p_rw_buff, 
                    p_cmd_param1, &u_cmd_param2);
                if (1 == i_op_status)
                {
                    strcpy(p_udt_ctxt->op_param1, p_cmd_param1);
                    p_udt_ctxt->op_param2 = u_cmd_param2;
                    udt_f_tcpserver_RecvFile(p_udt_ctxt);
                }
                else
                {
                    osp_socket_f_write(p_udt_ctxt->csockfd, 
                        p_udt_ctxt->p_rw_buff, i_recv_len);
                    udt_f_tcpserver_SendRecved(p_udt_ctxt);
                }
                break;
            }

        case UIT_CMD_TYPE_LISTFILE:
            {
                i_op_status = udt_f_incmd_cmdparam(p_udt_ctxt->p_rw_buff, 
                    p_cmd_param1, &u_cmd_param2);
                if (1 == i_op_status)
                {
                    strcpy(p_udt_ctxt->op_param1, p_cmd_param1);
                    p_udt_ctxt->op_param2 = u_cmd_param2;
                    udt_f_tcpserver_ListFile(p_udt_ctxt);
                }
                else
                {
                    osp_socket_f_write(p_udt_ctxt->csockfd, 
                        p_udt_ctxt->p_rw_buff, i_recv_len);
                    udt_f_tcpserver_SendRecved(p_udt_ctxt);
                }
                break;
            }

        default:
            {
                osp_socket_f_write(p_udt_ctxt->csockfd, 
                    p_udt_ctxt->p_rw_buff, i_recv_len);
                udt_f_tcpserver_SendRecved(p_udt_ctxt);
                break;
            }
        }

        OS_DBG_LOG(("iID:%u, TCPService, stop!\r\n", u_thread_id));
        OS_DBG_URC(("iID:%u, TCPService, stop!\r\n", u_thread_id));
    }

    return 0;
}

static uint32 ThreadUDPService(void* lpParam)
{
    sint32 i_recv_len = 0;
    sint32 i_echo_times = 0;

    int lenfrom;
    struct sockaddr addrfrom;
    struct sockaddr_in* p_in_addr;
    sint08 * p_peer_ipaddr = NULL;

    udt_context_t * p_udt_ctxt = (udt_context_t *)lpParam;

    if (p_udt_ctxt != NULL)
    {
        OS_DBG_LOG(("iID:%u, UDPEcho service, start!\r\n", p_udt_ctxt->iThreadID));
        OS_DBG_URC(("iID:%u, UDPEcho service, start!\r\n", p_udt_ctxt->iThreadID));
        while (1)
        {
            lenfrom = sizeof(struct sockaddr);
            memset(&addrfrom, 0, sizeof(struct sockaddr));
            memset(p_udt_ctxt->p_rw_buff, 0, UDT_MAX_BUFF_SIZE);
            
            i_recv_len = osp_socket_f_readfrom(p_udt_ctxt->csockfd,
                p_udt_ctxt->p_rw_buff, UDT_MAX_BUFF_SIZE, &addrfrom, &lenfrom);
            
            if(i_recv_len < 0)
            {
                OS_DBG_DBG(("UDP readfrom error:%d;\r\n", osp_socket_f_geterror()));
                break;
            }
            
            i_echo_times++;
            p_in_addr = (struct sockaddr_in*)(&(addrfrom));
            p_peer_ipaddr = inet_ntoa(p_in_addr->sin_addr);
            OS_DBG_LOG(("iID:%u, UDPEcho service, peer=%s, times=%d.\r\n",
                p_udt_ctxt->iThreadID, p_peer_ipaddr, i_echo_times));
            
            osp_socket_f_writeto(p_udt_ctxt->csockfd, 
                p_udt_ctxt->p_rw_buff, i_recv_len, &addrfrom, lenfrom);
            
            osp_timer_f_sleep(10);
        }
        
        OS_DBG_LOG(("iID:%u, UDPEcho service, stop!\r\n", p_udt_ctxt->iThreadID));
        OS_DBG_URC(("iID:%u, UDPEcho service, stop!\r\n", p_udt_ctxt->iThreadID));
        
        osp_socket_f_close(p_udt_ctxt->csockfd);
        free(p_udt_ctxt->p_rw_buff);
        free(p_udt_ctxt);
    }

    return 0;
}

static sint32 udt_f_logfile_new(void* arg)
{
    sint32 i_ret_val = 1;

    lxz_log_f_init(arg);

    return 0;
}

int udt_server_main(uint16 u_svr_port)
{
    sint08 * p_root_directory = NULL;

    OS_DBG_LOG(("<--Author: numax; Version: %s-->\r\n", UDT_SVR_VERSION_FULL));
    OS_DBG_LOG(("Usage:  Update time: %s %s\r\n", UDT_SVR_COMPILE_DATE, UDT_SVR_COMPILE_TIME));
    OS_DBG_LOG(("UDP-server: echo-service only;\r\n"));
    OS_DBG_LOG(("TCP-server: echo-server and simple upload/download;\r\n"));
    OS_DBG_LOG(("\r\n"));
    OS_DBG_LOG(("First Packet from TCP-client:\r\n"));
    OS_DBG_LOG(("UL-service: recved: (\"UT:%%s:%%s\",filename,offset);\r\n"));
    OS_DBG_LOG(("DL-service: recved: (\"DT:%%s:%%s\",filename,offset);\r\n"));
    OS_DBG_LOG(("Echo-service: All other recved;\r\n"));
    OS_DBG_LOG(("Listening on %d\r\n\r\n", u_svr_port));

    OS_DBG_URC(("<--Author: numax; Version: %s-->\r\n", UDT_SVR_VERSION_FULL));
    OS_DBG_URC(("Usage:  Update time: %s %s\r\n", UDT_SVR_COMPILE_DATE, UDT_SVR_COMPILE_TIME));
    OS_DBG_URC(("UDP-server: echo-service only;\r\n"));
    OS_DBG_URC(("TCP-server: echo-server and simple upload/download;\r\n"));
    OS_DBG_URC(("\r\n"));
    OS_DBG_URC(("First Packet from TCP-client:\r\n"));
    OS_DBG_URC(("UL-service: recved: (\"UT:%%s:%%s\",filename,offset);\r\n"));
    OS_DBG_URC(("DL-service: recved: (\"DT:%%s:%%s\",filename,offset);\r\n"));
    OS_DBG_URC(("Echo-service: All other recved;\r\n"));
    OS_DBG_URC(("Listening on %d\r\n\r\n", u_svr_port));

    p_root_directory = (uint08 *)malloc(LXZ_PATH_LENGTH_MAX);
    memset(p_root_directory, 0, LXZ_PATH_LENGTH_MAX);
    strcpy(p_root_directory, lxz_root_directory_f_get());
    lxz_exec_f_open(udt_f_logfile_new, p_root_directory, LXZ_LOGFILE_NEW_CYCLE);

    udt_f_udpserver_start(u_svr_port);
    udt_f_tcpserver_start(u_svr_port);

    free(p_root_directory);

    return 0;
}


